package com.kld.web.controller.system;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.util.ArrayUtil;
import com.kld.common.annotation.Log;
import com.kld.common.constant.Constants;
import com.kld.common.constant.UserConstants;
import com.kld.common.core.controller.BaseController;
import com.kld.common.core.domain.R;
import com.kld.common.core.domain.entity.SysDept;
import com.kld.common.core.domain.entity.SysUser;
import com.kld.common.core.domain.model.LoginUser;
import com.kld.common.enums.BusinessType;
import com.kld.common.helper.LoginHelper;
import com.kld.common.utils.StringUtils;
import com.kld.data.domain.po.SysTrans;
import com.kld.data.service.ISysTransService;
import com.kld.system.domain.SysDeptMdm;
import com.kld.system.domain.SysSyncTime;
import com.kld.system.domain.vo.SysUserMdmVo;
import com.kld.system.service.*;
import com.kld.web.constant.DataConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 部门信息
 *
 * @author Lion Li
 */
@Validated
@Api(value = "部门控制器", tags = {"部门管理"})
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/dept")
public class SysDeptController extends BaseController {

    private final ISysDeptService deptService;
    private final ISysUserService userService;
    private final ISysDeptMdmService deptMdmService;
    private final ISysUserMdmService userMdmService;
    private final ISysSyncTimeService syncTimeService;
    private final ISysTransService sysTransService;

    /**
     * 获取部门列表
     */
    @ApiOperation("获取部门列表")
    //@SaCheckPermission("system:dept:list")
    @GetMapping("/list")
    public R<List<SysDept>> list(SysDept dept) {
        List<SysDept> depts = deptService.selectDeptList(dept);
        return R.ok(depts);
    }


    /**
     * 获取部门列表
     */
    @ApiOperation("获取部门列表(全量数据)")
    @GetMapping("/listNoDataPermission")
    public R<List<SysDept>> listNoDataPermission(SysDept dept) {
        List<SysDept> depts = deptService.selectDeptListNoDataPermission(dept);
        return R.ok(depts);
    }

    /**
     * 获取部门列表
     */
    @ApiOperation("获取下级部门或单位列表")
    @GetMapping("/listDeptOrOrg")
    public R<List<SysDept>> listDeptAndOrg() {
        LoginUser user = LoginHelper.getLoginUser();
        SysDept dept = deptService.selectDeptById(user.getDeptId());
        List<SysDept> depts = new ArrayList<SysDept>();
        //如果是单位，则直接查询下级单位的虚拟机构级联列表
        if(Constants.SYS_DEPT_TYPE_ORG.equals(dept.getOrgType())){
            depts.add(dept);
            SysDept param  = new SysDept();
            param.setOrgType("dept");
            param.setParentId(dept.getDeptId());
            depts.addAll(deptService.selectDeptListForOrg(param));
        }
        //如果是部门，向上找到部门所属的实际单位，并查询下属的单层非虚拟单位
        if(Constants.SYS_DEPT_TYPE_DEPT.equals(dept.getOrgType())){
            Long deptId = deptService.selectParentOrgById(dept.getDeptId());
            depts.add(deptService.selectDeptById(deptId));
            SysDept param  = new SysDept();
            param.setOrgType("org");
            param.setParentId(deptId);
            depts.addAll(deptService.selectDeptListNoDataPermission(param));
        }
        return R.ok(depts);
    }

    /**
     * 获取部门列表
     */
    @ApiOperation("获取下级部门和单位")
    @GetMapping("/listDeptAndOrg")
    public R<List<SysDept>> listDept() {
        LoginUser user = LoginHelper.getLoginUser();
        SysDept dept = deptService.selectDeptById(user.getDeptId());
        List<SysDept> depts = new ArrayList<SysDept>();
        //如果是部门，向上找到部门所属的实际单位
        Long deptId = dept.getDeptId();
        SysDept param  = new SysDept();
        if(Constants.SYS_DEPT_TYPE_DEPT.equals(dept.getOrgType())){
            deptId = deptService.selectParentOrgById(dept.getDeptId());
            depts.add(deptService.selectDeptById(deptId));
            param.setOrgType("org");
            param.setParentId(deptId);
            //查询下属的单层非虚拟单位以及该单位的部门
            List<SysDept> childrenOrg = deptService.selectDeptListNoDataPermission(param);
            depts.addAll(childrenOrg);
            for (SysDept child:childrenOrg) {
                param.setOrgType("dept");
                param.setParentId(child.getDeptId());
                depts.addAll(deptService.selectDeptListForOrg(param));
            }
        }else{
            depts.add(dept);
            param.setOrgType("dept");
            param.setParentId(dept.getDeptId());
            //如果是单位，则直接查询下级单位的虚拟机构级联列表
            depts.addAll(deptService.selectDeptListForOrg(param));
        }
        return R.ok(depts);
    }



    /**
     * 查询部门列表（排除节点）
     */
    @ApiOperation("查询部门列表（排除节点）")
    @SaCheckPermission("system:dept:list")
    @GetMapping("/list/exclude/{deptId}")
    public R<List<SysDept>> excludeChild(@ApiParam("部门ID") @PathVariable(value = "deptId", required = false) Long deptId) {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        depts.removeIf(d -> d.getDeptId().equals(deptId)
            || ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
        return R.ok(depts);
    }

    /**
     * 根据部门编号获取详细信息
     */
    @ApiOperation("根据部门编号获取详细信息")
    @SaCheckPermission("system:dept:query")
    @GetMapping(value = "/{deptId}")
    public R<SysDept> getInfo(@ApiParam("部门ID") @PathVariable Long deptId) {
        deptService.checkDeptDataScope(deptId);
        return R.ok(deptService.selectDeptById(deptId));
    }

    /**
     * 获取部门下拉树列表
     */
    @ApiOperation("获取部门下拉树列表")
    @GetMapping("/treeselect")
    public R<List<Tree<Long>>> treeselect(SysDept dept) {
        return R.ok(deptService.buildDeptTreeSelect(dept));
    }

    /**
     * 加载对应角色部门列表树
     */
    @ApiOperation("加载对应角色部门列表树")
    @GetMapping(value = "/roleDeptTreeselect/{roleId}")
    public R<Map<String, Object>> roleDeptTreeselect(@ApiParam("角色ID") @PathVariable("roleId") Long roleId) {
        List<SysDept> depts = deptService.selectDeptList(new SysDept());
        Map<String, Object> ajax = new HashMap<>();
        ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
        ajax.put("depts", deptService.buildDeptTreeSelect(new SysDept()));
        return R.ok(ajax);
    }

    /**
     * 新增部门
     */
    @ApiOperation("新增部门")
    @SaCheckPermission("system:dept:add")
    @Log(title = "部门管理", businessType = BusinessType.INSERT)
    @PostMapping
    public R<Void> add(@Validated @RequestBody SysDept dept) {
        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
            return R.fail("新增部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        }
        return toAjax(deptService.insertDept(dept));
    }

    /**
     * 修改部门
     */
    @ApiOperation("修改部门")
    @SaCheckPermission("system:dept:edit")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public R<Void> edit(@Validated @RequestBody SysDept dept) {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        if (UserConstants.NOT_UNIQUE.equals(deptService.checkDeptNameUnique(dept))) {
            return R.fail("修改部门'" + dept.getDeptName() + "'失败，部门名称已存在");
        } else if (dept.getParentId().equals(deptId)) {
            return R.fail("修改部门'" + dept.getDeptName() + "'失败，上级部门不能是自己");
        } else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus())
            && deptService.selectNormalChildrenDeptById(deptId) > 0) {
            return R.fail("该部门包含未停用的子部门！");
        }
        return toAjax(deptService.updateDept(dept));
    }


    /**
     * 修改部门
     */
    @ApiOperation("级联修改部门类型")
    @SaCheckPermission("system:dept:edit")
    @Log(title = "部门管理", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/cascadeOrgType")
    public R<Void> editOrgType(@Validated @RequestBody SysDept dept) {
        Long deptId = dept.getDeptId();
        deptService.checkDeptDataScope(deptId);
        return toAjax(deptService.updateOrgType(dept));
    }


    /**
     * 删除部门
     */
    @ApiOperation("删除部门")
    @SaCheckPermission("system:dept:remove")
    @Log(title = "部门管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deptId}")
    public R<Void> remove(@ApiParam("部门ID串") @PathVariable Long deptId) {
        if (deptService.hasChildByDeptId(deptId)) {
            return R.fail("存在下级部门,不允许删除");
        }
        if (deptService.checkDeptExistUser(deptId)) {
            return R.fail("部门存在用户,不允许删除");
        }
        deptService.checkDeptDataScope(deptId);
        return toAjax(deptService.deleteDeptById(deptId));
    }


    /**
     * 从从库的数据库中同步数据
     */
    @ApiOperation("同步组织机构")
    @SaCheckPermission("system:dept:sync")
    @GetMapping("/sync")
    public R<Void> sync() {
        return toAjax(changeData());
    }



    private int changeData(){
        int rows = 0;
        //1.组织机构同步
//        int rows =  changeDeptData();
        SysTrans orgTrans = sysTransService.selectSysTransById(DataConstant.DATA_TRANS_ORG);
        if(orgTrans!=null){
            sysTransService.executeTransTask(orgTrans);
            rows += 1;
        }
        //大于0表示从从库中更新了组织机构数据，那么需要更新一下redis中的树和列表
        if(rows > 0){
            deptService.resetSysDeptTree();
        }
        //2.用户同步
        SysTrans userTrans = sysTransService.selectSysTransById(DataConstant.DATA_TRANS_USER);
        if(userTrans!=null){
            sysTransService.executeTransTask(userTrans);
            rows += 1;
        }
//       rows += changeUserData();
       return rows+1;
    }

    private int changeDeptData(){
        SysSyncTime syncTime = syncTimeService.selectSyncTimeById(1L);
        List<SysDeptMdm> deptMdms =  findDeptData(syncTime);
        int rows = 0;
        for (SysDeptMdm deptMdm:deptMdms) {
            SysDept dept = new SysDept();
            dept.setDeptId(deptMdm.getId());
            dept.setParentId(deptMdm.getParentId());
            dept.setAncestors(deptMdm.getParentIds()+",0");
            dept.setDeptName(deptMdm.getExtend3());
            dept.setDeptFallName(deptMdm.getOrgName());
            dept.setOrderNum(deptMdm.getSort());
            dept.setParentOrgId(deptMdm.getParentId());
            String del = "0";
            if(deptMdm.getDel() == 1){
                del = "2";
            }
            dept.setDelFlag(del);
            dept.setStatus("0");
            deptService.insertOrUpdateDeptNotCheck(dept);
            rows++;
        }

        syncTime = new SysSyncTime();
        syncTime.setId(1L);
        syncTime.setSyncType("DEPT");
        syncTime.setSyncTime(new Date());
        syncTimeService.insertOrUpdateSyncTime(syncTime);
        return rows;
    }

    private int changeUserData(){
        SysSyncTime syncTime = syncTimeService.selectSyncTimeById(2L);
        List<SysUserMdmVo> userMdms =  findUserData(syncTime);
        int rows = 0;
        for (SysUserMdmVo userMdmVo:userMdms) {
            SysUser user = new SysUser();
            user.setUserId(userMdmVo.getId());
            user.setUserName(userMdmVo.getLoginName());
            user.setNickName(userMdmVo.getDisplayName());
            user.setUserType("sys_user");
            String del = "0";
            if(userMdmVo.getDel() == 1){
                del = "2";
            }
            user.setDelFlag(del);
            user.setStatus("0");
            user.setDeptId(userMdmVo.getOrgId());
            userService.insertOrUpdateDeptNotCheck(user);
            rows++;
        }

        syncTime = new  SysSyncTime();
        syncTime.setId(2L);
        syncTime.setSyncType("USER");
        syncTime.setSyncTime(new Date());
        syncTimeService.insertOrUpdateSyncTime(syncTime);
        return rows;
    }
    /**
     * 从从库的数据库中查找对应的组织机构数据
     */
    private List<SysDeptMdm> findDeptData(SysSyncTime syncTime) {
        List<SysDeptMdm> depts = deptMdmService.selectDeptMdmList(syncTime);
        return depts;
    }

    /**
     * 从从库的数据库中查找对应的用户数据
     */
    private List<SysUserMdmVo> findUserData(SysSyncTime syncTime) {
        List<SysUserMdmVo> users = userMdmService.selectUserMdmList(syncTime);
        return users;
    }
}
